package com.hst.web.base.service;

import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.hst.core.ServiceContext;
import com.hst.core.dao.IORDao;
import com.hst.core.dao.ORQuery;
import com.hst.core.dao.ORQuery.Op;
import com.hst.core.entity.TDict;
import com.hst.core.json.JsonUtil;
import com.hst.core.meta.MetaRepository;
import com.hst.web.auth.po.LoginRequest;
import com.hst.web.auth.po.User;
import com.hst.web.base.entity.*;
import com.hst.web.base.ui.*;
import com.hst.web.common.utils.ConstantUtil;
import com.hst.web.common.utils.PapersNumberUtils;
import com.hst.web.sys.entity.TUser;
import com.hst.web.sys.entity.TUserRole;
import com.hst.web.sys.service.UserService;
import com.hst.web.sys.ui.EmployeeUpgrade;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.openxml4j.util.ZipSecureFile;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.ui.Model;
import org.springframework.web.multipart.MultipartFile;

import javax.transaction.Transactional;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.sql.Timestamp;
import java.util.*;
import java.util.Base64.Encoder;

@Service
@Transactional
public class EmployeeService {

    @Autowired
    IORDao dao;

    @Autowired
    MetaRepository mr;

    @Autowired
    UserService userService;

    static Logger logger = LoggerFactory.getLogger(EmployeeService.class);

    private static final String COMPANY_ADMIN = "comp_admin";

    /**
     * 人员操作状态：离职
     */
    private static final String OPTYPE_DEPART = "2";

    private Map<String, String> papersType = new HashMap<String, String>();

    /**
     * 导入企业员工
     *
     * @param m
     * @throws Exception
     */
    public void importCompanyEmployee(MultipartFile file, Model m, String companyCode) throws Exception {
        User u = (User) ServiceContext.getInstance().getUser();
        if (StringUtils.isEmpty(companyCode))
            companyCode = u.getCompanyCode();
        List<CompanyEmployee> excelList = parseCompanyEmpExcel2Meta(file, companyCode);

        Map<Integer, CompanyEmployee> failList = new HashMap<Integer, CompanyEmployee>();// 有错误的数据行
        Map<Integer, String> failMsgList = new HashMap<Integer, String>();// 错误数据行的对应错误信息
        Map<Integer, TCompanyEmployee> saveEmp = new HashMap<Integer, TCompanyEmployee>();// 将保存的人员信息
        Map<Integer, TDeptEmployee> saveDeptEmp = new HashMap<Integer, TDeptEmployee>();// 将保存的部门员工
        List<TDeptEmployee> companyEmpList = dao.list(TDeptEmployee.class,
                new ORQuery(Op.eq, "companyCode", companyCode));
        int i = 1;
        // int count_sucess = 0;

        // 公司员工
        for (CompanyEmployee e : excelList) {
            i++;
            try {
                // 验证
                PapersNumberUtils.validate(e.getPapersNumber(), e.getPapersType());
                for (int j = 0; j < i - 2; j++) {
                    if (e.getPapersType().equals(excelList.get(j).getPapersType())
                            && e.getPapersNumber().equals(excelList.get(j).getPapersNumber()))
                        throw new Exception("与导入数据的第" + (j + 2) + "行数据重复");
                }

                // 不存在人员记录则预先新增一条
                List<ORQuery> querys = new ArrayList<ORQuery>();
                querys.add(new ORQuery(Op.eq, "papersType", e.getPapersType()));
                querys.add(new ORQuery(Op.eq, "papersNumber", e.getPapersNumber()));
                List<TCompanyEmployee> list = dao.list(TCompanyEmployee.class, querys);
                if (list.size() == 0)
                    saveEmp.put(i, (TCompanyEmployee) mr.getMetaConvert("company-employee").toEntity(e));
                else
                    e.setEmployeeCode(list.get(0).getEmployeeCode());

                // 插入员工部门关系表
                if (e.getDeptCode() == null)            //用户填写的部门编码或名称不正确时,DeptCode=null
                    throw new Exception("部门编码或名称不正确");

//				for (TDeptEmployee p : companyEmpList) {
//					if (p.getEmployeeCode().equals(e.getEmployeeCode()))
//						throw new Exception("本企业下已存在该员工!");
//				}

                //员工在企业员工表或企业承包商员工表中不能重复
                List<ORQuery> query = new ArrayList<ORQuery>();
                query.add(new ORQuery(Op.eq, "employeeCode", e.getEmployeeCode()));
                List<TDeptEmployee> deptEmployeeList = dao.list(TDeptEmployee.class, query);
                if (deptEmployeeList.size() > 0) {
                    List<String> listCompany = new ArrayList<String>();
                    for (TDeptEmployee d : deptEmployeeList) {
                        TCompanyInfo c1 = dao.get(TCompanyInfo.class, d.getCompanyCode());
                        if (c1 != null) {
                            listCompany.add(c1.getCompanyName());
                        } else {            //所属企业已被删除时,做离职处理
                            this.companyEmployeeResign(d);
                        }
                    }
                    if (listCompany.size() > 0) {
                        throw new Exception("企业员工在(" + StringUtils.join(listCompany, ",") + ")中已存在,请先离职！");
                    }
                }
                query.clear();
                query.add(new ORQuery(Op.eq, "employeeCode", e.getEmployeeCode()));
                List<TEmployeeContractorDept> employeeContractorDeptList = dao.list(TEmployeeContractorDept.class, query);
                if (employeeContractorDeptList.size() > 0) {
                    List<String> listCompanyContractor = new ArrayList<String>();
                    for (TEmployeeContractorDept d : employeeContractorDeptList) {
                        TCompanyInfo c1 = dao.get(TCompanyInfo.class, d.getCompanyCode());
                        if (c1 != null) {
                            listCompanyContractor.add(c1.getCompanyName());
                        } else {            //所属企业已被删除时,做离职处理
                            this.contractorEmployeeResign(d);
                        }
                    }
                    if (listCompanyContractor.size() > 0) {
                        throw new Exception("承包商员工在(" + StringUtils.join(listCompanyContractor, ",") + ")中已存在,请先离职！");
                    }
                }

                TDeptEmployee dpe = new TDeptEmployee();
                if (StringUtils.isNoneEmpty(e.getDeptCode())) {
                    dpe.setDeptCode(e.getDeptCode());
                }
                dpe.setEmployeeCode(e.getEmployeeCode());
                dpe.setCompanyCode(companyCode);
                saveDeptEmp.put(i, dpe);

                // count_sucess++;
            } catch (Exception ex) {
                failList.put(i, e);
                failMsgList.put(i, ex.getMessage());
            }
        }

        //
        if (failList.size() == 0)
            for (Map.Entry<Integer, TDeptEmployee> x : saveDeptEmp.entrySet()) {
                // 不存在人员记录新增保存
                if (saveEmp.containsKey(x.getKey())) {
                    TCompanyEmployee e = saveEmp.get(x.getKey());
                    insertEmp2db(e);
                    x.getValue().setEmployeeCode(e.getEmployeeCode());
                    dao.save(x.getValue());
                } else
                    dao.save(x.getValue());

                //入职
                TCompanyEmployee e = dao.get(TCompanyEmployee.class, x.getValue().getEmployeeCode());
                e.setJobStatus("1");    //状态改为入职
                dao.update(e);

                //人员操作记录
                TEmployeeOperate eo = new TEmployeeOperate();
                eo.setCompanyCode(x.getValue().getCompanyCode());
                eo.setDeptCode(x.getValue().getDeptCode());
                eo.setEmployeeCode(x.getValue().getEmployeeCode());
                eo.setOpType("1");        // 入职
                eo.setOpTime(new Timestamp(new Date().getTime()));
                eo.setOpUserid(u.getId());
                dao.save(eo);
            }


        if (failList.size() > 0) {
            m.addAttribute("fail", JsonUtil.toString(failList));
            m.addAttribute("failMsg", failMsgList);
        }
        m.addAttribute("sucess", true);
    }

    /**
     * 导入承包商员工
     *
     * @throws IOException
     * @throws Exception
     */
    public void importContractorEmployee(String companyCode, MultipartFile file, Model m) throws IOException {
        User u = (User) ServiceContext.getInstance().getUser();
        if (StringUtils.isEmpty(companyCode))
            companyCode = ((User) ServiceContext.getInstance().getUser()).getCompanyCode();
        List<ContractorEmployee> excelList = parseContractorEmpExcel2Meta(file, companyCode);

        Map<Integer, ContractorEmployee> failList = new HashMap<Integer, ContractorEmployee>();
        Map<Integer, String> failMsgList = new HashMap<Integer, String>();
        Map<Integer, TCompanyEmployee> saveEmp = new HashMap<Integer, TCompanyEmployee>();
        Map<Integer, TEmployeeContractorDept> savEcd = new HashMap<Integer, TEmployeeContractorDept>();

        int i = 1;
        // int count_sucess = 0;
        // 验证
        for (ContractorEmployee e : excelList) {
            i++;
            try {
                PapersNumberUtils.validate(e.getPapersNumber(), e.getPapersType());
                for (int j = 0; j < i - 2; j++) {
                    if (e.getPapersType().equals(excelList.get(j).getPapersType())
                            && e.getPapersNumber().equals(excelList.get(j).getPapersNumber()))
                        throw new Exception("与第" + (j + 2) + "行数据重复");
                }

                // 不存在人员记录则预先新增一条
                List<ORQuery> querys = new ArrayList<ORQuery>();
                querys.add(new ORQuery(Op.eq, "papersType", e.getPapersType()));
                querys.add(new ORQuery(Op.eq, "papersNumber", e.getPapersNumber()));
                List<TCompanyEmployee> list = dao.list(TCompanyEmployee.class, querys);
                if (list.size() == 0)
                    saveEmp.put(i, (TCompanyEmployee) mr.getMetaConvert("contractor-employee").toEntity(e));
                else
                    e.setEmployeeCode(list.get(0).getEmployeeCode());

                // 插入承包商部门关系表
                if (e.getContractorCode() == null)
                    throw new Exception("无效的承包商别名");
//				for (TEmployeeContractorDept p : empList) {
//					if (p.getEmployeeCode().equals(e.getEmployeeCode()))
//						throw new Exception("人员在本企业的承包商下已存在！");
//				}

                //员工在企业员工表或企业承包商员工表中不能重复
                List<ORQuery> query = new ArrayList<ORQuery>();
                query.add(new ORQuery(Op.eq, "employeeCode", e.getEmployeeCode()));
                List<TDeptEmployee> deptEmployeeList = dao.list(TDeptEmployee.class, query);
                if (deptEmployeeList.size() > 0) {
                    List<String> listCompany = new ArrayList<String>();
                    for (TDeptEmployee d : deptEmployeeList) {
                        TCompanyInfo c1 = dao.get(TCompanyInfo.class, d.getCompanyCode());
                        if (c1 != null) {
                            listCompany.add(c1.getCompanyName());
                        } else {            //所属企业已被删除时,做离职处理
                            this.companyEmployeeResign(d);
                        }
                    }
                    if (listCompany.size() > 0) {
                        throw new Exception("企业员工在(" + StringUtils.join(listCompany, ",") + ")中已存在,请先离职！");
                    }
                }
                query.clear();
                query.add(new ORQuery(Op.eq, "employeeCode", e.getEmployeeCode()));
                List<TEmployeeContractorDept> employeeContractorDeptList = dao.list(TEmployeeContractorDept.class, query);
                if (employeeContractorDeptList.size() > 0) {
                    List<String> listCompanyContractor = new ArrayList<String>();
                    for (TEmployeeContractorDept d : employeeContractorDeptList) {
                        TCompanyInfo c1 = dao.get(TCompanyInfo.class, d.getCompanyCode());
                        if (c1 != null) {
                            listCompanyContractor.add(c1.getCompanyName());
                        } else {            //所属企业已被删除时,做离职处理
                            this.contractorEmployeeResign(d);
                        }
                    }
                    if (listCompanyContractor.size() > 0) {
                        throw new Exception("承包商员工在(" + StringUtils.join(listCompanyContractor, ",") + ")中已存在,请先离职！");
                    }
                }

                TEmployeeContractorDept ecd = new TEmployeeContractorDept();
                ecd.setCompanyCode(companyCode);
                ecd.setEmployeeCode(e.getEmployeeCode());
                ecd.setContractorCode(e.getContractorCode());
                savEcd.put(i, ecd);

                // count_sucess++;
            } catch (Exception ex) {
                failList.put(i, e);
                failMsgList.put(i, ex.getMessage());
            }
        }

        //
        if (failList.size() == 0)
            for (Map.Entry<Integer, TEmployeeContractorDept> x : savEcd.entrySet()) {
                // 不存在人员记录新增保存
                if (saveEmp.containsKey(x.getKey())) {
                    TCompanyEmployee e = saveEmp.get(x.getKey());
                    insertEmp2db(e);
                    x.getValue().setEmployeeCode(e.getEmployeeCode());
                }
                dao.save(x.getValue());

                //入职
                TCompanyEmployee e = dao.get(TCompanyEmployee.class, x.getValue().getEmployeeCode());
                e.setJobStatus("1");    //状态改为入职
                dao.update(e);

                //人员操作记录
                TEmployeeOperate eo = new TEmployeeOperate();
                eo.setCompanyCode(x.getValue().getCompanyCode());
                eo.setContractorCode(x.getValue().getContractorCode());
                eo.setEmployeeCode(x.getValue().getEmployeeCode());
                eo.setOpType("1");// 入职
                eo.setOpTime(new Timestamp(new Date().getTime()));
                eo.setOpUserid(u.getId());

                dao.save(eo);
            }

        if (failList.size() > 0) {
            m.addAttribute("fail", JsonUtil.toString(failList));
            m.addAttribute("failMsg", failMsgList);
        }
        m.addAttribute("sucess", true);
    }

    private XSSFWorkbook getWorkbook(MultipartFile file) throws IOException {
        String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
        if (!".xls".equals(suffix) && !".xlsx".equals(suffix)) {
            throw new IOException("不支持该文件类型");
        }
        if (file.getSize() > 5 * 1024 * 1024) {
            throw new IOException("上传文件不得超过5MB");
        }
        InputStream is = file.getInputStream();
        ZipSecureFile.setMinInflateRatio(-1.0d);
        return new XSSFWorkbook(is);
    }

    private List<CompanyEmployee> parseCompanyEmpExcel2Meta(MultipartFile file, String companyCode) throws IOException {
        XSSFWorkbook workbook = getWorkbook(file);
        Sheet sheet = workbook.getSheetAt(0);
        if (papersType.isEmpty())
            dao.list(TDict.class, new ORQuery(Op.eq, "name", "papersType")).stream()
                    .forEach((e) -> papersType.put(e.getText(), e.getId()));
        ORQuery qCompany = new ORQuery(Op.eq, "companyCode", companyCode);

        List<CompanyEmployee> list = new ArrayList<CompanyEmployee>();
        // 企业部门编码->部门表主键编码
        Map<String, String> code2DeptCode = new HashMap<String, String>();
        Map<String, String> code2DeptCodeName = new HashMap<String, String>();
        for (TCompanyDept dt : dao.list(TCompanyDept.class, qCompany)) {
            if (!code2DeptCode.containsKey(dt.getCode()))
                code2DeptCode.put(dt.getCode(), dt.getDeptCode());
            if (!code2DeptCodeName.containsKey(dt.getDeptName()))
                code2DeptCodeName.put(dt.getDeptName(), dt.getDeptCode());
        }
        for (int i = 1; i <= sheet.getLastRowNum(); i++) {
            Row row = sheet.getRow(i);
            CompanyEmployee t = new CompanyEmployee();

            Cell cell = row.getCell(0);
            if (cell != null && StringUtils.isNotEmpty(row.getCell(0).toString().trim())) {
                // 姓名
                t.setFullname(row.getCell(0).toString().trim());
                // 证件号
                if (CellType.STRING.equals(row.getCell(1).getCellType()))
                    t.setPapersNumber(row.getCell(1).toString().trim());
                if (CellType.NUMERIC.equals(row.getCell(1).getCellType()))
                    t.setPapersNumber(row.getCell(1).toString().replaceAll(".0", "").trim());
                // 证件类型
                t.setPapersType(papersType.get(row.getCell(2).toString().trim()));

                //如果证件类型为身份证"01",则将证件号号码中的"x"改为"X",进行保存
                if ("01".equals(t.getPapersType())) {
                    String papersNumber = t.getPapersNumber();
                    t.setPapersNumber(papersNumber.replace('x', 'X'));
                }
                // 部门
                String code = row.getCell(3) != null ? row.getCell(3).toString().trim() : null;
                if (StringUtils.isEmpty(code)) {        //用户未填写部门时DeptCode=""
                    t.setDeptCode("");
                } else {
                    if (code != null && code2DeptCode.containsKey(code.trim())) {    //判断部门编码是否存在
                        t.setDeptCode(code2DeptCode.get(code.trim()));
                    } else if (code != null && code2DeptCodeName.containsKey(code.trim())) {        //判断部门名称是否存在
                        t.setDeptCode(code2DeptCodeName.get(code.trim()));
                    } else {                            //用户填写的部门编码不存在时,DeptCode=null
                        t.setDeptCode(null);
                    }
                }
                list.add(t);
            }
        }

        return list;
    }

    private List<ContractorEmployee> parseContractorEmpExcel2Meta(MultipartFile file, String companyCode)
            throws IOException {
        XSSFWorkbook workbook = getWorkbook(file);
        if (papersType.isEmpty())
            dao.list(TDict.class, new ORQuery(Op.eq, "name", "papersType")).stream()
                    .forEach((e) -> papersType.put(e.getText(), e.getId()));

        Sheet sheet = workbook.getSheetAt(0);
        ORQuery qCompany = new ORQuery(Op.eq, "companyCode", companyCode);

        // 承包商别名->承包商code
        Map<String, String> alias2Contractor = new HashMap<String, String>();
        for (TCompanyContractor e : dao.list(TCompanyContractor.class, qCompany)) {
            if (!alias2Contractor.containsKey(e.getContractorAlisa()))
                alias2Contractor.put(e.getContractorAlisa(), e.getContractorCode());
        }

        List<ContractorEmployee> list = new ArrayList<ContractorEmployee>();
        for (int i = 1; i <= sheet.getLastRowNum(); i++) {
            Row row = sheet.getRow(i);
            ContractorEmployee t = new ContractorEmployee();

            // 姓名
            Cell cell = row.getCell(0);
            if (cell != null && StringUtils.isNotEmpty(row.getCell(0).toString().trim())) {
                t.setFullname(row.getCell(0).toString().trim());
                // 证件号
                if (CellType.STRING.equals(row.getCell(1).getCellType()))
                    t.setPapersNumber(row.getCell(1).toString().trim());
                if (CellType.NUMERIC.equals(row.getCell(1).getCellType()))
                    t.setPapersNumber(row.getCell(1).toString().replaceAll(".0", "").trim());
                // 证件类型
                t.setPapersType(papersType.get(row.getCell(2).toString().trim()));

                //如果证件类型为身份证"01",则将证件号号码中的"x"改为"X",进行保存
                if ("01".equals(t.getPapersType())) {
                    String papersNumber = t.getPapersNumber();
                    t.setPapersNumber(papersNumber.replace('x', 'X'));
                }

                // 承包商
                String cont = row.getCell(3).toString().trim();
                if (alias2Contractor.containsKey(cont.trim())) {
                    t.setContractorCode(alias2Contractor.get(cont.trim()));
                }else {
                    t.setContractorCode(null);
                }
                // 人员类型
                Object personType = row.getCell(4);
                if (personType != null) {
                    dao.list(TDict.class, new ORQuery(Op.eq, "name", "employeeTypeId")).stream()
                            .forEach((e) -> papersType.put(e.getText(), e.getId()));
                    logger.info("人员类型是:"+papersType.get(personType.toString().trim()));
                    t.setEmployeeTypeId(papersType.get(personType.toString().trim()));
                }
                list.add(t);
            }
        }
        return list;
    }

    /**
     * 导入数据,(证件类型，证件号)
     *
     * @param e
     * @throws Exception
     */
    public void insertEmp2db(TCompanyEmployee e) {
        e.setIdentifyFlag(ConstantUtil.IDENTIFYFLAG_NOT);
        e.setPushflag(ConstantUtil.PUSHFLAG_NOT);
        e.setReviewStatus(ConstantUtil.REVIEWSTATUS_NOT);
        e.setCheckStatus(ConstantUtil.CHECKSTATUS_NOT);
        dao.save(e);
        // 在account表中添加 Employeecode信息
        List<ORQuery> qAccountInfo = new ArrayList<ORQuery>();
//		qAccountInfo.add(new ORQuery(Op.eq, "fullname", e.getFullname()));
        qAccountInfo.add(new ORQuery(Op.eq, "papersNumber", e.getPapersNumber()));
        qAccountInfo.add(new ORQuery(Op.eq, "papersType", e.getPapersType()));
        for (TAccountIdentity ai : dao.list(TAccountIdentity.class, qAccountInfo)) {
            ai.setEmployeeCode(e.getEmployeeCode());
            dao.update(ai);
        }
    }

    // 退回转企业申请
    public void transBack(PersoneltransferInfo tran, Model m) throws JsonGenerationException, JsonMappingException,
            IOException, IllegalAccessException, InvocationTargetException {
        User user = (User) ServiceContext.getInstance().getUser();
        TPersoneltransferInfo trans = new TPersoneltransferInfo();
        BeanUtils.copyProperties(trans, tran);
        trans.setTransStatus("02");
        trans.setAcceptUserid(user.getId());
        trans.setAcceptTime(new Timestamp(new Date().getTime()));
        trans = dao.update(trans);
        m.addAttribute("trans", JsonUtil.toString(trans));
    }

    // 通过转企业申请
    public void transPass(PersoneltransferInfo tran, Model m) throws IllegalAccessException, InvocationTargetException,
            JsonGenerationException, JsonMappingException, IOException {
        User user = (User) ServiceContext.getInstance().getUser();

        //取得申请方操作人的uid
        TPersoneltransferInfo trans = dao.get(TPersoneltransferInfo.class, tran.getId());
        String createUserid = trans.getCreateUserid();
        String uid = null;
        if (StringUtils.isNotEmpty(createUserid)) {
            List<TUser> tus = dao.list(TUser.class, new ORQuery(Op.eq, "operatorNbr", createUserid));
            if (tus.size() == 1) {
                TUser tu = tus.get(0);
                uid = tu.getId();
            }
        }

        BeanUtils.copyProperties(trans, tran);
        trans.setTransStatus("01");
        trans.setAcceptUserid(user.getId());
        trans.setAcceptTime(new Timestamp(new Date().getTime()));
        trans = dao.update(trans);

        String employeeCode = trans.getEmployeeCode();
        String companyCodeOld = trans.getCompanycodeOld();
        String companyCode = trans.getCompanyCode();
        String deptCodeOld = trans.getDeptCodeOld();
        String deptCode = trans.getDeptCode();

        //先做离职操作
        List<ORQuery> querys = new ArrayList<ORQuery>();
        querys.add(new ORQuery(Op.eq, "employeeCode", employeeCode));
        querys.add(new ORQuery(Op.eq, "companyCode", companyCodeOld));
        List<TDeptEmployee> list = dao.list(TDeptEmployee.class, querys);
        for (TDeptEmployee deptEmployee : list) {
            TEmployeeOperate op = new TEmployeeOperate();
            op.setOpType("2");
            op.setEmployeeCode(deptEmployee.getEmployeeCode());
            op.setCompanyCode(deptEmployee.getCompanyCode());
            op.setDeptCode(deptEmployee.getDeptCode());
            op.setOpTime(new Timestamp(new Date().getTime()));
            op.setOpUserid(uid);
            op.setOpRemark("人员转企业离职操作");
            dao.save(op);
            dao.delete(deptEmployee);
        }

        //再做入职操作
        TDeptEmployee deptEmployee;
        deptEmployee = new TDeptEmployee();
        deptEmployee.setEmployeeCode(employeeCode);
        deptEmployee.setCompanyCode(companyCode);
        deptEmployee.setDeptCode(deptCode);
        dao.save(deptEmployee);

        TEmployeeOperate op = new TEmployeeOperate();
        op.setEmployeeCode(deptEmployee.getEmployeeCode());
        op.setCompanyCode(deptEmployee.getCompanyCode());
        op.setDeptCode(deptEmployee.getDeptCode());
        op.setOpType("1");// 入职
        op.setOpTime(new Timestamp(new Date().getTime()));
        op.setOpUserid(user.getId());
        op.setOpRemark("人员转企业入职操作");
        dao.save(op);

        m.addAttribute("trans", JsonUtil.toString(trans));
    }

    // 通过人员转入企业审批
    public void TransApprovePass(PersoneltransferInfo tran, Model m) throws Exception {
        User user = (User) ServiceContext.getInstance().getUser();

        //取得申请方操作人的uid
        TPersoneltransferInfo trans = dao.get(TPersoneltransferInfo.class, tran.getId());
        String createUserid = trans.getCreateUserid();
        String uid = null;
        if (StringUtils.isNotEmpty(createUserid)) {
            List<TUser> tus = dao.list(TUser.class, new ORQuery(Op.eq, "operatorNbr", createUserid));
            if (tus.size() == 1) {
                TUser tu = tus.get(0);
                uid = tu.getId();
            }
        }

        BeanUtils.copyProperties(trans, tran);
        String employeeCode = trans.getEmployeeCode();
        String companyCodeOld = trans.getCompanycodeOld();
        String companyCode = trans.getCompanyCode();
        String deptCodeOld = trans.getDeptCodeOld();
        String deptCode = trans.getDeptCode();

        //判断人员是否已经存在于入职企业
        List<ORQuery> query = new ArrayList<ORQuery>();
        query.add(new ORQuery(Op.eq, "companyCode", companyCode));
        query.add(new ORQuery(Op.eq, "employeeCode", employeeCode));
        List<TDeptEmployee> deptEmployeeList = dao.list(TDeptEmployee.class, query);
        if (deptEmployeeList.size() > 0) {
            List<String> listCompany = new ArrayList<String>();
            for (TDeptEmployee d : deptEmployeeList) {
                TCompanyInfo c1 = dao.get(TCompanyInfo.class, d.getCompanyCode());
                listCompany.add(c1.getCompanyName());
            }
            throw new Exception("该员工在企业(" + StringUtils.join(listCompany, ",") + ")中已入职,请做退回处理！");
        }

        //先做离职操作
        List<ORQuery> querys = new ArrayList<ORQuery>();
        querys.add(new ORQuery(Op.eq, "employeeCode", employeeCode));
        querys.add(new ORQuery(Op.eq, "companyCode", companyCodeOld));
        List<TDeptEmployee> list = dao.list(TDeptEmployee.class, querys);
        for (TDeptEmployee deptEmployee : list) {
            TEmployeeOperate op = new TEmployeeOperate();
            op.setOpType("2");
            op.setEmployeeCode(deptEmployee.getEmployeeCode());
            op.setCompanyCode(deptEmployee.getCompanyCode());
            op.setDeptCode(deptEmployee.getDeptCode());
            op.setOpTime(new Timestamp(new Date().getTime()));

            op.setOpUserid(user.getId());
            op.setOpRemark("人员转入企业离职操作");
            dao.save(op);
            dao.delete(deptEmployee);
        }

        //再做入职操作
        TDeptEmployee deptEmployee;
        deptEmployee = new TDeptEmployee();
        deptEmployee.setEmployeeCode(employeeCode);
        deptEmployee.setCompanyCode(companyCode);
        deptEmployee.setDeptCode(deptCode);
        dao.save(deptEmployee);

        TEmployeeOperate op = new TEmployeeOperate();
        op.setEmployeeCode(deptEmployee.getEmployeeCode());
        op.setCompanyCode(deptEmployee.getCompanyCode());
        op.setDeptCode(deptEmployee.getDeptCode());
        op.setOpType("1");// 入职
        op.setOpTime(new Timestamp(new Date().getTime()));
        op.setOpUserid(uid);
        op.setOpRemark("人员转企业入职操作");
        dao.save(op);

        trans.setTransStatus("01");
        trans.setAcceptUserid(user.getId());
        trans.setAcceptTime(new Timestamp(new Date().getTime()));
        trans = dao.update(trans);

        m.addAttribute("trans", JsonUtil.toString(trans));
    }

    // 通过转承包商申请
    public void transPassCont(PersoneltransferInfo tran, Model m) throws IllegalAccessException,
            InvocationTargetException, JsonGenerationException, JsonMappingException, IOException {
        User user = (User) ServiceContext.getInstance().getUser();

        //取得申请方操作人的uid
        TPersoneltransferInfo trans = dao.get(TPersoneltransferInfo.class, tran.getId());
        String createUserid = trans.getCreateUserid();
        String uid = null;
        if (StringUtils.isNotEmpty(createUserid)) {
            List<TUser> tus = dao.list(TUser.class, new ORQuery(Op.eq, "operatorNbr", createUserid));
            if (tus.size() == 1) {
                TUser tu = tus.get(0);
                uid = tu.getId();
            }
        }

        BeanUtils.copyProperties(trans, tran);
        trans.setTransStatus("01");
        trans.setAcceptUserid(user.getId());
        trans.setAcceptTime(new Timestamp(new Date().getTime()));
        trans = dao.update(trans);

        String employeeCode = trans.getEmployeeCode();
        String companyCodeOld = trans.getCompanycodeOld();
        String companyCode = trans.getCompanyCode();
        String contractorCodeOld = trans.getContractorCodeOld();
        String contractorCode = trans.getContractorCode();

        //先做离职操作
        List<ORQuery> querys = new ArrayList<ORQuery>();
        querys.add(new ORQuery(Op.eq, "employeeCode", employeeCode));
        querys.add(new ORQuery(Op.eq, "companyCode", companyCodeOld));
        List<TEmployeeContractorDept> list = dao.list(TEmployeeContractorDept.class, querys);
        for (TEmployeeContractorDept employeeContractorDept : list) {
            TEmployeeOperate op = new TEmployeeOperate();
            op.setOpType("2");
            op.setEmployeeCode(employeeContractorDept.getEmployeeCode());
            op.setCompanyCode(employeeContractorDept.getCompanyCode());
            op.setContractorCode(employeeContractorDept.getContractorCode());
            op.setOpTime(new Timestamp(new Date().getTime()));
            op.setOpUserid(uid);
            op.setOpRemark("人员转承包商离职操作");
            dao.save(op);
            dao.delete(employeeContractorDept);
        }

        //再做入职操作
        TEmployeeContractorDept employeeContractorDept;
        employeeContractorDept = new TEmployeeContractorDept();
        employeeContractorDept.setEmployeeCode(employeeCode);
        employeeContractorDept.setCompanyCode(companyCode);
        employeeContractorDept.setContractorCode(contractorCode);
        dao.save(employeeContractorDept);

        TEmployeeOperate op = new TEmployeeOperate();
        op.setEmployeeCode(employeeContractorDept.getEmployeeCode());
        op.setCompanyCode(employeeContractorDept.getCompanyCode());
        op.setContractorCode(employeeContractorDept.getContractorCode());
        op.setOpType("1");// 入职
        op.setOpTime(new Timestamp(new Date().getTime()));
        op.setOpUserid(user.getId());
        op.setOpRemark("人员转承包商入职操作");
        dao.save(op);

        m.addAttribute("trans", JsonUtil.toString(trans));
    }

    public void reviewApprove(List<CompanyEmployeeReview> list, String remark) {
        for (CompanyEmployeeReview e : list) {
            e.setReviewStatus("1");// 通过
            TReivewHistory h = new TReivewHistory();
            h.setEmployeeCode(e.getEmployeeCode());
            h.setReviewStatus(e.getReviewStatus());
            h.setReviewType("0");// 人员复核
            h.setRemark(remark);
            dao.save(h);
            dao.update(mr.getMetaConvert("employee-review").toEntity(e));
        }
    }

    public void reviewReject(List<CompanyEmployeeReview> list, String remark) {
        for (CompanyEmployeeReview e : list) {
            e.setReviewStatus("2");// 不通过
            TReivewHistory h = new TReivewHistory();
            h.setEmployeeCode(e.getEmployeeCode());
            h.setReviewStatus(e.getReviewStatus());
            h.setReviewType("0");// 人员复核
            h.setRemark(remark);
            dao.save(h);
            dao.update(mr.getMetaConvert("employee-review").toEntity(e));
        }
    }

    /**
     * 升级企业管理员
     *
     * @throws IOException
     * @throws JsonMappingException
     * @throws JsonGenerationException
     */
    public void companyUpgrade(CompanyInfo company, LoginRequest login, Model m)
            throws JsonGenerationException, JsonMappingException, IOException {
        List<ORQuery> querys = new ArrayList<ORQuery>();
        querys.add(new ORQuery(Op.eq, "operatorNbr", login.getUserid()));
        List<TUser> users = dao.list(TUser.class, querys);
        Encoder encoder = Base64.getEncoder();
        if (users.size() > 0) {
            TUser user = users.get(0);
            if (new String(encoder.encode(login.getPasswd().getBytes())).equals(user.getPassword())) { // 账号密码相同直接转变所属公司
                user.setLoginName(login.getCaptcha());
                user = dao.update(user);
                querys = new ArrayList<ORQuery>();
                querys.add(new ORQuery(Op.eq, "userid", user.getId()));
                List<TUserRole> rels = dao.list(TUserRole.class, querys);
                for (TUserRole rel : rels) {
                    dao.delete(rel);
                }
                TUserRole rel = new TUserRole();
                rel.setUserid(user.getId());
                rel.setRoleid(COMPANY_ADMIN);
                dao.save(rel);

                querys = new ArrayList<ORQuery>();
                querys.add(new ORQuery(Op.eq, "employeeCode", user.getEmployeeCode()));
                List<TDeptEmployee> depts = dao.list(TDeptEmployee.class, querys);
                if (depts.size() > 0) {
                    TDeptEmployee dept = depts.get(0);
                    if (company.getCompanyCode().equals(dept.getCompanyCode())) {
                        m.addAttribute("success", "success");
                        m.addAttribute("user", JsonUtil.toString(user));
                    } else {
                        dept.setCompanyCode(company.getCompanyCode());
                        dao.update(dept);
                        m.addAttribute("success", "success");
                        m.addAttribute("user", JsonUtil.toString(user));
                    }
                }
            } else {
                m.addAttribute("msg", "此账号已经存在,且账号密码不匹配");
            }
            return;
        }

        querys.clear();
        querys.add(new ORQuery(Op.eq, "userName", login.getUserid()));
        List<TAccountInfo> listAccountInfo = dao.list(TAccountInfo.class, querys);
        if (listAccountInfo.size() > 0) {
            m.addAttribute("msg", "APP用户表中已经存在此账号");
            return;
        }

        TCompanyEmployee employee = new TCompanyEmployee();
        employee.setCheckStatus("0");
        employee.setIdentifyFlag("01");
        employee.setReviewStatus("0");
        employee.setPushflag("0");
        employee = dao.save(employee);
        TDeptEmployee dept = new TDeptEmployee();
        dept.setCompanyCode(company.getCompanyCode());
        dept.setEmployeeCode(employee.getEmployeeCode());
        dao.save(dept);

        TUser user = new TUser();
        user.setEmployeeCode(employee.getEmployeeCode());
        user.setPassword(new String(encoder.encode(login.getPasswd().getBytes())));
        user.setOperatorNbr(login.getUserid());
        user.setLoginName(login.getCaptcha());
        user.setValidflag("1");
        user.setUserType("2");
        user.setUserTypeOld(ConstantUtil.USETYPEMAP.get(COMPANY_ADMIN));
        user = dao.save(user);

        TAccountInfo accountInfo = new TAccountInfo();
        accountInfo.setUserName(login.getUserid());
        accountInfo.setPassword(new String(encoder.encode(login.getPasswd().getBytes())));
        dao.save(accountInfo);

        TUserRole rel = new TUserRole();
        rel.setUserid(user.getId());
        rel.setRoleid(COMPANY_ADMIN);
        dao.save(rel);
        m.addAttribute("success", "success");
        m.addAttribute("user", JsonUtil.toString(user));
    }

    /**
     * 员工撤职
     */
    public void delgrade(EmployeeUpgrade grade, Model m) {
        String employeeCode = grade.getEmployeeCode();
        List<ORQuery> querys = new ArrayList<ORQuery>();
        querys.add(new ORQuery(Op.eq, "employeeCode", employeeCode));
        List<TUser> users = dao.list(TUser.class, querys);
        if (users.size() > 0) {
            TUser user = users.get(0);
            user.setUserTypeOld(ConstantUtil.USETYPEMAP.get("personal"));
            querys = new ArrayList<ORQuery>();
            querys.add(new ORQuery(Op.eq, "userid", user.getId()));
            List<TUserRole> rels = dao.list(TUserRole.class, querys);
            for (TUserRole rel : rels) {
                dao.delete(rel);
            }

            //同步更新TAccountInfo表的useType字段
            String userName = userService.vaildateAccountIdentity(employeeCode);
            if (StringUtils.isNotEmpty(userName)) {
                TAccountInfo accountInfo = dao.get(TAccountInfo.class, userName);
                if (accountInfo != null) {
                    accountInfo.setUseType(ConstantUtil.USETYPEMAP.get("personal"));
                    dao.update(accountInfo);
                }
            }
            m.addAttribute("success", "success");
        }
    }

    /**
     * 企业员工离职
     *
     * @return
     * @throws
     * @param    TDeptEmployee 待离职员工企业员工关联
     */
    public void companyEmployeeResign(TDeptEmployee e) {
        List<ORQuery> querys = new ArrayList<ORQuery>();

        //删除企业员工关联信息
        User u = (User) ServiceContext.getInstance().getUser();
        TEmployeeOperate op = new TEmployeeOperate();
        op.setOpType(OPTYPE_DEPART);
        op.setEmployeeCode(e.getEmployeeCode());
        op.setCompanyCode(e.getCompanyCode());
        op.setDeptCode(e.getDeptCode());
        op.setOpTime(new Timestamp(new Date().getTime()));
        op.setOpUserid(u.getId());
        dao.save(op);
        dao.delete(e);

        //如果用户从所有企业中都离职时，则清除用户的通行证和审批状态
        querys.clear();
        querys.add(new ORQuery(Op.eq, "employeeCode", e.getEmployeeCode()));
        List<TDeptEmployee> deptEmployeeList = dao.list(TDeptEmployee.class, querys);
        List<TEmployeeContractorDept> employeeContractorDeptList = dao.list(TEmployeeContractorDept.class, querys);
        if (deptEmployeeList.size() == 0 && employeeContractorDeptList.size() == 0) {
            TCompanyEmployee companyEmployee = dao.get(TCompanyEmployee.class, e.getEmployeeCode());
            if (companyEmployee != null) {
                companyEmployee.setIssueNo(null);
                companyEmployee.setEndExpirydate(null);
                companyEmployee.setCheckStatus("0");
                companyEmployee.setJobStatus("2");
                dao.update(companyEmployee);
            }

            //清除用户所属车辆的通行证和审批状态
            querys.clear();
            querys.add(new ORQuery(Op.eq, "employeeCode", e.getEmployeeCode()));
            List<TVehicleInfo> vehicleInfoList = dao.list(TVehicleInfo.class, querys);
            for (TVehicleInfo vehicleInfo : vehicleInfoList) {
                vehicleInfo.setIssueNo(null);
                vehicleInfo.setEndExpirydate(null);
                vehicleInfo.setCheckStatus("0");
                dao.update(vehicleInfo);
            }
        }
    }

    /**
     * 承包商员工离职
     */
    public void contractorEmployeeResign(TEmployeeContractorDept e) {
        List<ORQuery> querys = new ArrayList<ORQuery>();

        //删除企业承包商员工关联信息
        User u = (User) ServiceContext.getInstance().getUser();
        TEmployeeOperate op = new TEmployeeOperate();
        op.setOpType(OPTYPE_DEPART);
        op.setEmployeeCode(e.getEmployeeCode());
        op.setCompanyCode(e.getCompanyCode());
        op.setContractorCode(e.getContractorCode());
        op.setOpTime(new Timestamp(new Date().getTime()));
        op.setOpUserid(u.getId());
        dao.save(op);
        dao.delete(e);

        //如果用户从所有企业中都离职时，则清除用户的通行证和审批状态
        querys.clear();
        querys.add(new ORQuery(Op.eq, "employeeCode", e.getEmployeeCode()));
        List<TDeptEmployee> deptEmployeeList = dao.list(TDeptEmployee.class, querys);
        List<TEmployeeContractorDept> employeeContractorDeptList = dao.list(TEmployeeContractorDept.class, querys);
        if (deptEmployeeList.size() == 0 && employeeContractorDeptList.size() == 0) {
            TCompanyEmployee companyEmployee = dao.get(TCompanyEmployee.class, e.getEmployeeCode());
            if (companyEmployee != null) {
                companyEmployee.setIssueNo(null);
                companyEmployee.setEndExpirydate(null);
                companyEmployee.setCheckStatus("0");
                companyEmployee.setJobStatus("2");
                dao.update(companyEmployee);
            }

            //清除用户所属车辆的通行证和审批状态
            querys.clear();
            querys.add(new ORQuery(Op.eq, "employeeCode", e.getEmployeeCode()));
            List<TVehicleInfo> vehicleInfoList = dao.list(TVehicleInfo.class, querys);
            for (TVehicleInfo vehicleInfo : vehicleInfoList) {
                vehicleInfo.setIssueNo(null);
                vehicleInfo.setEndExpirydate(null);
                vehicleInfo.setCheckStatus("0");
                dao.update(vehicleInfo);
            }

            //清除用户所有合同状态
            querys.clear();
            querys.add(new ORQuery(Op.eq, "employeeCode", e.getEmployeeCode()));
            List<TContract> tContractsList = dao.list(TContract.class, querys);
            for (TContract tContract: tContractsList) {
                tContract.setUpUser(u.getId());
                tContract.setStatus("2");
                tContract.setIsDel("1");
                dao.update(tContract);
            }
        }
    }
}
